package net.lastcoder.ifserver.server;

import net.lastcoder.ifserver.Constants;
import net.lastcoder.ifserver.Globals;
import net.lastcoder.ifserver.command.CommandManager;
import net.lastcoder.ifserver.nio.Connection;
import net.lastcoder.ifserver.nio.ConnectionCloseListener;
import net.lastcoder.ifserver.nio.NIOConnection;
import net.lastcoder.ifserver.session.Session;
import net.lastcoder.ifserver.session.UlaID;

import org.apache.log4j.Appender;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * auth: WenYF
 * date: 2016/11/23
 */
class ServerHandler extends IoHandlerAdapter {
    private static final Logger Log = LoggerFactory.getLogger(ServerHandler.class);

    protected static final String CONNECTION = "CONNECTION";

    private CommandManager commandManager;
    private ServerManager terminateManager;
    private ConnectionCloseListener connectionCloseListener = new ConnectionCloseListener() {
        @Override
        public void onConnectionClose(Object handback) {
            ServerSession session = (ServerSession) handback;
            terminateManager.removeTerminateSession(session);
        }
    };

    ServerHandler() {
        commandManager = CommandManager.getInstance();
        terminateManager = ServerManager.getInstance();
    }

    @Override
    public void sessionOpened(IoSession session) throws Exception {
        final NIOConnection connection = createNIOConnection(session);
        session.setAttribute(CONNECTION, connection);
        session.getConfig().setReaderIdleTime(getMaxIdleTime());
    }

    @Override
    public void sessionClosed(IoSession session) throws Exception {
        super.sessionClosed(session);

        final Connection connection = (Connection) session.getAttribute(CONNECTION);
        if (connection != null) {
            connection.close();
        }
    }

    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        if (session.getIdleCount(status) >= 1) {
            // Get the connection for this session
            final Connection connection = (Connection) session.getAttribute(CONNECTION);
            if (connection != null) {
                connection.deliverRawData("timeout".getBytes());
                // Close idle connection
                if (Log.isDebugEnabled()) {
                    Log.debug("ConnectionHandler: Closing connection that has been idle: " + connection);
                }
                connection.close();
            }
        }
    }

    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        Log.warn("Closing connection due to exception in session: " + session, cause);

        try {
            final Connection connection = (Connection) session.getAttribute(CONNECTION);
            byte[] error = new byte[1];
            error[0] = '\0';
            connection.deliverRawData(error);
        } finally {
            final Connection connection = (Connection) session.getAttribute(CONNECTION);
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        String str = (String) message;
        Connection connection = (Connection) session.getAttribute(CONNECTION);
    }

    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
        super.messageSent(session, message);
    }

    private NIOConnection createNIOConnection(IoSession session) {
        return new NIOConnection(session);
    }

    private int getMaxIdleTime() {
        return Globals.getXMLProperty("terminate.session.idle.time", Constants.DAY * 10) / 1000;
    }

}
